#include "StdAfx.h"
/// Copyright 2012, Alex Averian, Yonan Research
/// Released under BSD Licence



#include "qbrowser.h"




#include <urlmon.h>  //CoInternetSetFeatureEnabled
#pragma comment (lib, "Urlmon.lib")


using namespace micro::utils;
using namespace micro::gui;
using namespace micro::browser;


const int MAX_ZOOM = 1000;
const int MIN_ZOOM = 10;
const int NORMAL_ZOOM = 100;
const int INVALID_ZOOM = -1;
const int IN_OUT_ZOOM_STEP = 25;




//HKCU\Software\Microsoft\Internet Explorer\Main\FeatureControl\FEATURE_TABBED_BROWSING
//myco.exe=0x00000001



// NWMF_FORCEWINDOW: User opened a link in a new window.
// NWMF_FORCETAB: User opened a link in a new tab.
// NWMF_INACTIVETAB: An inactive tab tried to open a window.



/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
CAXWindow::CAXWindow() : m_cRefs( 1 ), m_hWnd( nullptr ), m_pUnk( nullptr ),  m_pIWebBrowser2( nullptr ), m_pWebObject( nullptr )
{
}

CAXWindow::~CAXWindow()
{
    //ASSERT( m_cRefs == 1 );
}

// void CAXWindow::CreateControl( BSTR bstrClsid )
// {
//     CLSID   clsid;
//     CLSIDFromString( bstrClsid, &clsid );
//     CreateControl( clsid );
// }



void CAXWindow::CreateControl( CLSID clsid )
{
    CoCreateInstance( clsid, nullptr, CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER, IID_IUnknown, ( void ** )&m_pUnk );

    if ( !m_pUnk )
        return;


    HRESULT hr = m_pUnk->QueryInterface( IID_IOleObject, ( void ** )&m_pWebObject );

    if ( FAILED( hr ) )
        return;

    m_pWebObject->SetClientSite( ( IOleClientSite * ) this );


    m_pUnk->QueryInterface( IID_IWebBrowser2, ( void ** )&m_pIWebBrowser2 );


    if ( ! m_pIWebBrowser2 )
        return;


    m_pIWebBrowser2->put_Silent( VARIANT_TRUE );
    //m_pIWebBrowser2->put_RegisterAsBrowser(VARIANT_TRUE);



//     IPersistStreamInit * ppsi;
//     hr = m_pUnk->QueryInterface( IID_IPersistStreamInit, ( void ** )&ppsi );
//
//     if ( SUCCEEDED( hr ) )
//     {
//         ppsi->InitNew();
//         ppsi->Release();
//     }


    //necesar
    // 	if(! m_url.IsEmpty() )
    // 		Navigate(m_url);
    // 	else
    Navigate( _T( "about:blank" ) );





    // If control wasn't quick-activated, then connect sinks now.
// 	if (hr != S_QUICKACTIVATED)
// 	{
// 		m_dwEventSink = ConnectSink(m_iidEvents, &m_xEventSink);
// 		m_dwPropNotifySink = ConnectSink(IID_IPropertyNotifySink,
// 			&m_xPropertyNotifySink);
// 	}
// 	m_dwNotifyDBEvents = ConnectSink(IID_INotifyDBEvents, &m_xNotifyDBEvents);

}



bool CAXWindow::GetBusy()const
{
    bool busy = false;

    if ( m_pIWebBrowser2 )
    {

        VARIANT_BOOL    variant_bool;

        HRESULT hr = m_pIWebBrowser2->get_Busy( &variant_bool );

        if ( SUCCEEDED( hr ) )
        {
            busy = ( variant_bool == VARIANT_TRUE );
        }

    }

    return busy;
}

QString CAXWindow::GetLocationName() const
{

    QString location_name;

    if ( m_pIWebBrowser2 )
    {

        BSTR location_name_BSTR = nullptr;

        HRESULT hr = m_pIWebBrowser2->get_LocationName( &location_name_BSTR );

        if ( hr == S_OK )
        {
            location_name = location_name_BSTR;
        }

        ::SysFreeString( location_name_BSTR );

    }

    return location_name;
}

QString CAXWindow::GetLocationURL() const
{
    QString location_URL;

    ASSERT( m_pIWebBrowser2 );

    BSTR location_URL_BSTR = nullptr;

    HRESULT hr = m_pIWebBrowser2->get_LocationURL( &location_URL_BSTR );

    if ( hr == S_OK )
    {
        location_URL = location_URL_BSTR;
    }

    ::SysFreeString( location_URL_BSTR );


    return location_URL;
}




HRESULT CAXWindow::QueryInterface( REFIID riid, void ** ppvObject )
{
    if ( !ppvObject )
        return E_POINTER;

    *ppvObject = nullptr;

    static const QITAB qit[] =
    {
        QITABENT( CAXWindow, IOleClientSite ),
        QITABENT( CAXWindow, IOleInPlaceSite ),
        QITABENT( CAXWindow, IOleInPlaceFrame ),
        QITABENT( CAXWindow, IOleInPlaceUIWindow ),
        QITABENT( CAXWindow, IOleControlSite ),
        //QITABENT( CAXWindow, IOleWindow ),
        QITABENT( CAXWindow, IDocHostUIHandler ),
        QITABENT( CAXWindow, IDispatch ),
        { 0 },
    };
    return QISearch( this, qit, riid, ppvObject ); //calls AddRef
}


ULONG CAXWindow::AddRef()
{
    return ++m_cRefs;
}

ULONG CAXWindow::Release()
{
    return --m_cRefs;
}

HRESULT CAXWindow::CanInPlaceActivate()
{
    return S_OK;
}

HRESULT CAXWindow::ContextSensitiveHelp( BOOL fEnterMode )
{
    UNREFERENCED_PARAMETER( fEnterMode );
    return E_NOTIMPL;
}

HRESULT CAXWindow::DeactivateAndUndo()
{
    return E_NOTIMPL;
}

HRESULT CAXWindow::DiscardUndoState()
{
    return E_NOTIMPL;
}

HRESULT CAXWindow::EnableModeless( BOOL fEnable )
{
    UNREFERENCED_PARAMETER( fEnable );
    return E_NOTIMPL;
}

HRESULT CAXWindow::GetBorder( LPRECT lprectBorder )
{
    UNREFERENCED_PARAMETER( lprectBorder );
    return E_NOTIMPL;
}

HRESULT CAXWindow::GetContainer( LPOLECONTAINER * ppContainer )
{
    //*ppContainer = nullptr;
    UNREFERENCED_PARAMETER( ppContainer );
    return E_NOINTERFACE;
}


HRESULT CAXWindow::GetExtendedControl( IDispatch ** ppDisp )
{
    if ( ppDisp == nullptr )
        return E_INVALIDARG;

    *ppDisp = ( IDispatch * )this;
    ( *ppDisp )->AddRef();


    return S_OK;
}

HRESULT CAXWindow::GetIDsOfNames( REFIID riid, OLECHAR ** rgszNames, unsigned int cNames, LCID lcid, DISPID * rgdispid )
{
    UNREFERENCED_PARAMETER( ( IID )riid );		// IID cast required for the MinGW compiler
    UNREFERENCED_PARAMETER( rgszNames );
    UNREFERENCED_PARAMETER( cNames );
    UNREFERENCED_PARAMETER( lcid );

    *rgdispid = DISPID_UNKNOWN;
    return DISP_E_UNKNOWNNAME;
}

HRESULT CAXWindow::GetMoniker( DWORD dwAssign, DWORD dwWhichMoniker, LPMONIKER * ppMk )
{
    UNREFERENCED_PARAMETER( dwAssign );
    UNREFERENCED_PARAMETER( dwWhichMoniker );
    UNREFERENCED_PARAMETER( ppMk );
    return E_NOTIMPL;
}

HRESULT CAXWindow::GetTypeInfo( unsigned int itinfo, LCID lcid, ITypeInfo ** pptinfo )
{
    UNREFERENCED_PARAMETER( itinfo );
    UNREFERENCED_PARAMETER( lcid );
    UNREFERENCED_PARAMETER( pptinfo );
    return E_NOTIMPL;
}

HRESULT CAXWindow::GetTypeInfoCount( unsigned int * pctinfo )
{
    UNREFERENCED_PARAMETER( pctinfo );
    return E_NOTIMPL;
}

HRESULT CAXWindow::GetWindow( HWND * lphwnd )
{
    if ( !IsWindow( m_hWnd ) )
        return S_FALSE;

    *lphwnd = m_hWnd;
    return S_OK;
}

HRESULT CAXWindow::GetWindowContext ( IOleInPlaceFrame ** ppFrame, IOleInPlaceUIWindow ** ppIIPUIWin,
                                      LPRECT lprcPosRect, LPRECT lprcClipRect, LPOLEINPLACEFRAMEINFO lpFrameInfo )
{
    *ppFrame = ( IOleInPlaceFrame * )this;
    *ppIIPUIWin = nullptr;



    GetClientRect( m_hWnd, lprcPosRect );
    GetClientRect( m_hWnd, lprcClipRect );


    lpFrameInfo->cb             = sizeof( OLEINPLACEFRAMEINFO );
    lpFrameInfo->fMDIApp        = FALSE;
    lpFrameInfo->hwndFrame      = m_hWnd;
    lpFrameInfo->haccel         = 0;
    lpFrameInfo->cAccelEntries  = 0;

    //( *ppFrame )->AddRef();
    return S_OK;
}

HRESULT CAXWindow::InsertMenus( HMENU hmenuShared, LPOLEMENUGROUPWIDTHS lpMenuWidths )
{
    UNREFERENCED_PARAMETER( hmenuShared );
    UNREFERENCED_PARAMETER( lpMenuWidths );
    return E_NOTIMPL;
}

HRESULT CAXWindow::Invoke( DISPID dispid, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS * pdispparams, VARIANT * pvarResult, EXCEPINFO * pexecinfo, unsigned int * puArgErr )
{
    UNREFERENCED_PARAMETER( dispid );
    UNREFERENCED_PARAMETER( ( IID )riid );		// IID cast required for the MinGW compiler
    UNREFERENCED_PARAMETER( lcid );
    UNREFERENCED_PARAMETER( wFlags );
    UNREFERENCED_PARAMETER( pdispparams );
    UNREFERENCED_PARAMETER( pvarResult );
    UNREFERENCED_PARAMETER( pexecinfo );
    UNREFERENCED_PARAMETER( puArgErr );

    return DISP_E_MEMBERNOTFOUND;
}

HRESULT CAXWindow::OnControlInfoChanged()
{
    return E_NOTIMPL;
}

HRESULT CAXWindow::OnFocus( BOOL fGotFocus )
{
    UNREFERENCED_PARAMETER( fGotFocus );
    return E_NOTIMPL;
}

HRESULT CAXWindow::OnPosRectChange( LPCRECT lprcPosRect )
{
    UNREFERENCED_PARAMETER( lprcPosRect );
    return S_OK;
}

HRESULT CAXWindow::OnShowWindow( BOOL fShow )
{
    UNREFERENCED_PARAMETER( fShow );
    return S_OK;
}

void CAXWindow::Remove()
{
    if ( !m_pUnk )
        return;


    if ( m_pWebObject )
    {
        m_pWebObject->Close( OLECLOSE_NOSAVE );
        m_pWebObject->SetClientSite( nullptr );
        m_pWebObject->Release();
    }

    IOleInPlaceObject * pipo;
    HRESULT hr = m_pUnk->QueryInterface( IID_IOleInPlaceObject, ( void ** )&pipo );

    if ( SUCCEEDED( hr ) )
    {
        pipo->UIDeactivate();
        pipo->InPlaceDeactivate();
        pipo->Release();
    }

    m_pIWebBrowser2->Release();
    m_pIWebBrowser2 = nullptr;

    m_pUnk->Release();
    m_pUnk = nullptr;
}

void CAXWindow::SetFocus( BOOL fFocus )
{
    if ( !m_pUnk )
        return;

    if ( fFocus )
    {
        m_pWebObject->DoVerb( OLEIVERB_UIACTIVATE, nullptr, this, 0, m_hWnd, &m_rcControl );

    }
}

IHTMLDocument2 * CAXWindow::GetDocument()
{


    ASSERT( m_pIWebBrowser2 );
    IHTMLDocument2 * document = nullptr;


    // get browser document's dispatch interface

    IDispatch * document_dispatch = nullptr;

    HRESULT hr = m_pIWebBrowser2->get_Document( &document_dispatch );

    if ( S_OK == hr &&  document_dispatch  )
    {

        // get the actual document interface

        hr = document_dispatch->QueryInterface( IID_IHTMLDocument2,  ( void ** )&document );

        // release dispatch interface

        document_dispatch->Release();

    }

    return document;
}
IUnknown * CAXWindow::GetUnknown()
{
    if ( !m_pUnk )
        return nullptr;

    m_pUnk->AddRef();
    return m_pUnk;
}

void CAXWindow::Write( LPCTSTR string )
{
    ASSERT( m_pIWebBrowser2 );


    // get document interface

    IHTMLDocument2 * document = GetDocument();

    if ( document )
    {

        // construct text to be written to browser as SAFEARRAY

        SAFEARRAY * safe_array = SafeArrayCreateVector( VT_VARIANT, 0, 1 );

        VARIANT	* variant;

        SafeArrayAccessData( safe_array, ( LPVOID * )&variant );

        variant->vt      = VT_BSTR;
        //QString str = string;
        variant->bstrVal =	 ( BSTR )SysAllocString( string ) ;

        SafeArrayUnaccessData( safe_array );
        // no need for SafeArrayDestroy(safe_array);

        // write SAFEARRAY to browser document

        document->write( safe_array );


        document->Release();


        //document = nullptr;

    }


}

void CAXWindow::Clear()
{
    ASSERT( m_pIWebBrowser2 );


    // if document interface available, close/re-open document to clear display
    IHTMLDocument2	* document	= GetDocument();
    HRESULT			hr			= S_OK;

    if ( document == nullptr )
        return;


    // close and re-open document to empty contents
    document->close();


    VARIANT		open_name;
    VARIANT		open_features;
    VARIANT		open_replace;
    IDispatch	* open_window	= nullptr;

    ::VariantInit( &open_name );

    open_name.vt      = VT_BSTR;
    open_name.bstrVal = ::SysAllocString( L"_self" );

    ::VariantInit( &open_features );
    ::VariantInit( &open_replace );

    BSTR bstr = SysAllocString( L"text/html" );
    hr = document->open( bstr,
                         open_name,
                         open_features,
                         open_replace,
                         &open_window );


    ::VariantClear( &open_name );
    ::VariantClear( &open_features );
    ::VariantClear( &open_replace );
    ::SysFreeString( bstr );



    if ( hr == S_OK )
    {
        Refresh();
    }

    if ( open_window != nullptr )
    {
        open_window->Release();
    }

    if ( document != nullptr )
    {
        document->Release();
    }

}

void CAXWindow::Navigate( LPCTSTR pTChar )
{
    ASSERT( m_pIWebBrowser2 );


    // Navigate to our web page
    VARIANT vURL;
    vURL.vt = VT_BSTR;
    vURL.bstrVal = SysAllocString( /*TCharToWide*/( pTChar ) );
    VARIANT ve1, ve2, ve3, ve4;
    ve1.vt = VT_EMPTY;
    ve2.vt = VT_EMPTY;
    ve3.vt = VT_EMPTY;
    ve4.vt = VT_EMPTY;

    m_pIWebBrowser2->Navigate2( &vURL, &ve1, &ve2, &ve3, &ve4 );

    VariantClear( &vURL );	// Also frees memory allocated by SysAllocateString
}

// Navigation operations

void CAXWindow::GoBack()
{
    if ( m_pIWebBrowser2 )
    {
        m_pIWebBrowser2->GoBack();
    }
}

void CAXWindow::GoForward()
{
    if ( m_pIWebBrowser2 )
    {
        m_pIWebBrowser2->GoForward();
    }
}

void CAXWindow::GoHome()
{
    if ( m_pIWebBrowser2 )
    {
        m_pIWebBrowser2->GoHome();
    }
}
void CAXWindow::GoSearch()
{
    if ( m_pIWebBrowser2 )
    {
        m_pIWebBrowser2->GoSearch();
    }
}


void CAXWindow::Refresh()
{
    if ( m_pIWebBrowser2 )
    {
        m_pIWebBrowser2->Refresh();
    }
}




//////////////////////////////////////////////////////////////////////////
//  void CAXWindow::SetRegisterAsBrowser(BOOL bNewValue)
// { ASSERT(m_pIWebBrowser2 != NULL); m_pIWebBrowser2->put_RegisterAsBrowser((short) (bNewValue ? AFX_OLE_TRUE : AFX_OLE_FALSE)); }
//
//  void CAXWindow::SetRegisterAsDropTarget(BOOL bNewValue)
// { ASSERT(m_pIWebBrowser2 != NULL); m_pIWebBrowser2->put_RegisterAsDropTarget((short) (bNewValue ? AFX_OLE_TRUE : AFX_OLE_FALSE)); }
//
//  void CAXWindow::SetTheaterMode(BOOL bNewValue)
// { ASSERT(m_pIWebBrowser2 != NULL); m_pIWebBrowser2->put_TheaterMode((short) (bNewValue ? AFX_OLE_TRUE : AFX_OLE_FALSE)); }
//
//  void CAXWindow::SetVisible(BOOL bNewValue)
// { ASSERT(m_pIWebBrowser2 != NULL); m_pIWebBrowser2->put_Visible((short) (bNewValue ? AFX_OLE_TRUE : AFX_OLE_FALSE)); }
//
//  void CAXWindow::SetMenuBar(BOOL bNewValue)
// { ASSERT(m_pIWebBrowser2 != NULL); m_pIWebBrowser2->put_MenuBar((short) (bNewValue ? AFX_OLE_TRUE : AFX_OLE_FALSE)); }
//
//  void CAXWindow::SetToolBar(int nNewValue)
// { ASSERT(m_pIWebBrowser2 != NULL); m_pIWebBrowser2->put_ToolBar(nNewValue); }
//
//  void CAXWindow::SetOffline(BOOL bNewValue)
// { ASSERT(m_pIWebBrowser2 != NULL); m_pIWebBrowser2->put_Offline((short) (bNewValue ? AFX_OLE_TRUE : AFX_OLE_FALSE)); }
//
//  void CAXWindow::SetSilent(BOOL bNewValue)
// { ASSERT(m_pIWebBrowser2 != NULL); m_pIWebBrowser2->put_Silent((short) (bNewValue ? AFX_OLE_TRUE : AFX_OLE_FALSE)); }
//
//  void CAXWindow::GoBack()
// { ASSERT(m_pIWebBrowser2 != NULL); m_pIWebBrowser2->GoBack(); }
//
//  void CAXWindow::GoForward()
// { ASSERT(m_pIWebBrowser2 != NULL); m_pIWebBrowser2->GoForward(); }
//
//  void CAXWindow::GoHome()
// { ASSERT(m_pIWebBrowser2 != NULL); m_pIWebBrowser2->GoHome(); }
//
//  void CAXWindow::GoSearch()
// { ASSERT(m_pIWebBrowser2 != NULL); m_pIWebBrowser2->GoSearch(); }
//
//  void CAXWindow::Refresh()
// { ASSERT(m_pIWebBrowser2 != NULL); m_pIWebBrowser2->Refresh(); }
//
//  void CAXWindow::Refresh2(int nLevel)
// { ASSERT(m_pIWebBrowser2 != NULL); m_pIWebBrowser2->Refresh2(COleVariant((long) nLevel, VT_I4)); }
//
//  void CAXWindow::Stop()
// { ASSERT(m_pIWebBrowser2 != NULL); m_pIWebBrowser2->Stop(); }
//
//  void CAXWindow::SetFullScreen(BOOL bNewValue)
// { ASSERT(m_pIWebBrowser2 != NULL); m_pIWebBrowser2->put_FullScreen((short) (bNewValue ? AFX_OLE_TRUE : AFX_OLE_FALSE)); }
//
//  void CAXWindow::SetAddressBar(BOOL bNewValue)
// { ASSERT(m_pIWebBrowser2 != NULL); m_pIWebBrowser2->put_AddressBar((short) (bNewValue ? AFX_OLE_TRUE : AFX_OLE_FALSE)); }
//
//  void CAXWindow::SetHeight(long nNewValue)
// { ASSERT(m_pIWebBrowser2 != NULL); m_pIWebBrowser2->put_Height(nNewValue); }
//
//  void CAXWindow::SetWidth(long nNewValue)
// { ASSERT(m_pIWebBrowser2 != NULL); m_pIWebBrowser2->put_Width(nNewValue); }
//
//  void CAXWindow::PutProperty(LPCTSTR lpszPropertyName, long lValue)
// { ASSERT(m_pIWebBrowser2 != NULL); ASSERT(m_pIWebBrowser2 != NULL); PutProperty(lpszPropertyName, COleVariant(lValue, VT_UI4)); }
//
//  void CAXWindow::PutProperty(LPCTSTR lpszPropertyName, short nValue)
// { ASSERT(m_pIWebBrowser2 != NULL); ASSERT(m_pIWebBrowser2 != NULL); PutProperty(lpszPropertyName, COleVariant(nValue, VT_UI2)); }
//
//  void CAXWindow::PutProperty(LPCTSTR lpszPropertyName, LPCTSTR lpszValue)
// { ASSERT(m_pIWebBrowser2 != NULL); ASSERT(m_pIWebBrowser2 != NULL); PutProperty(lpszPropertyName, COleVariant(lpszValue, VT_BSTR)); }
//
//  void CAXWindow::PutProperty(LPCTSTR lpszPropertyName, double dValue)
// { ASSERT(m_pIWebBrowser2 != NULL); ASSERT(m_pIWebBrowser2 != NULL); PutProperty(lpszPropertyName, COleVariant(dValue)); }
//
//  void CAXWindow::SetTop(long nNewValue)
// { ASSERT(m_pIWebBrowser2 != NULL); m_pIWebBrowser2->put_Top(nNewValue); }
//
//  void CAXWindow::SetLeft(long nNewValue)
// { ASSERT(m_pIWebBrowser2 != NULL); m_pIWebBrowser2->put_Left(nNewValue); }
//
//  void CAXWindow::SetStatusBar(BOOL bNewValue)
// { ASSERT(m_pIWebBrowser2 != NULL); m_pIWebBrowser2->put_StatusBar((short) (bNewValue ? AFX_OLE_TRUE : AFX_OLE_FALSE)); }



//////////////////////////////////////////////////////////////////////////
HRESULT CAXWindow::OnUIActivate()
{
    return S_OK;
}

HRESULT CAXWindow::OnUIDeactivate( BOOL fUndoable )
{
    UNREFERENCED_PARAMETER( fUndoable );
    return E_NOTIMPL;
}





inline STDMETHODIMP CAXWindow::SetBorderSpace( LPCBORDERWIDTHS lpborderwidths )
{

    UNREFERENCED_PARAMETER( lpborderwidths );
    return E_NOTIMPL;
}

void CAXWindow::Stop()
{
    if ( m_pIWebBrowser2 )
    {
        m_pIWebBrowser2->Stop();
    }
}



inline STDMETHODIMP CAXWindow::SetActiveObject( IOleInPlaceActiveObject * pActiveObject, LPCOLESTR lpszObjName )
{
    UNREFERENCED_PARAMETER( pActiveObject );
    UNREFERENCED_PARAMETER( lpszObjName );
    return E_NOTIMPL;
}

inline STDMETHODIMP CAXWindow::RequestNewObjectLayout()
{
    return E_NOTIMPL;
}

inline STDMETHODIMP CAXWindow::Scroll( SIZE scrollExtent )
{
    UNREFERENCED_PARAMETER( scrollExtent );
    return E_NOTIMPL;
}

inline STDMETHODIMP CAXWindow::RequestBorderSpace( LPCBORDERWIDTHS lpborderwidths )
{
    UNREFERENCED_PARAMETER( lpborderwidths );
    return E_NOTIMPL;
}

inline STDMETHODIMP CAXWindow::RemoveMenus( HMENU hmenuShared )
{
    UNREFERENCED_PARAMETER( hmenuShared );
    return E_NOTIMPL;
}

HRESULT CAXWindow::LockInPlaceActive( BOOL fLock )
{
    UNREFERENCED_PARAMETER( fLock );
    return E_NOTIMPL;
}

HRESULT CAXWindow::OnInPlaceActivate()
{
    return S_OK;
}

HRESULT CAXWindow::OnInPlaceDeactivate()
{
    return S_OK;
}

inline STDMETHODIMP CAXWindow::SaveObject()
{
    return E_NOTIMPL;
}

void CAXWindow::SetLocation( int x, int y, int width, int height )
{
    m_rcControl.SetRect( x, y, x + width, y + height );

    if ( !m_pUnk )
        return;

    IOleInPlaceObject * pipo;
    HRESULT hr = m_pUnk->QueryInterface( IID_IOleInPlaceObject, ( void ** )&pipo );

    if ( FAILED( hr ) )
        return;


    pipo->SetObjectRects( &m_rcControl, &m_rcControl );
    pipo->Release();
}

void CAXWindow::TranslateKey( MSG msg )
{
    if ( !m_pUnk )
        return;

    IOleInPlaceActiveObject * pao;
    HRESULT hr = m_pUnk->QueryInterface( IID_IOleInPlaceActiveObject, ( void ** )&pao );

    if ( FAILED( hr ) )
        return;

    pao->TranslateAccelerator( &msg );
    pao->Release();
}

STDMETHODIMP CAXWindow::TranslateAccelerator( LPMSG pMsg, DWORD grfModifiers )
{
    UNREFERENCED_PARAMETER( pMsg );
    UNREFERENCED_PARAMETER( grfModifiers );
    return S_FALSE;
}

STDMETHODIMP CAXWindow::TranslateAccelerator( LPMSG lpmsg, WORD wID )
{
    UNREFERENCED_PARAMETER( lpmsg );
    UNREFERENCED_PARAMETER( wID );
    return S_OK;
}

STDMETHODIMP CAXWindow::TransformCoords( POINTL * pptlHimetric, POINTF * pptfContainer, DWORD dwFlags )
{
    UNREFERENCED_PARAMETER( pptlHimetric );
    UNREFERENCED_PARAMETER( pptfContainer );
    UNREFERENCED_PARAMETER( dwFlags );
    return E_NOTIMPL;
}

STDMETHODIMP CAXWindow::ShowPropertyFrame()
{
    return E_NOTIMPL;
}

STDMETHODIMP CAXWindow::ShowObject()
{
    return S_OK;
}

// Called from the browser object's TranslateAccelerator routines to translate key strokes to commands.
STDMETHODIMP CAXWindow::TranslateAccelerator( LPMSG lpMsg, const GUID * pguidCmdGroup, DWORD nCmdID )
{

    return( S_FALSE );
}

void CAXWindow::SetVisible( BOOL fVisible )
{
    if ( !m_pUnk )
        return;

    if ( fVisible )
    {
        m_pWebObject->DoVerb( OLEIVERB_INPLACEACTIVATE, nullptr, this, 0, m_hWnd, &m_rcControl );
        m_pWebObject->DoVerb( OLEIVERB_SHOW, nullptr, this, 0, m_hWnd, &m_rcControl );
    }
    else
        m_pWebObject->DoVerb( OLEIVERB_HIDE, nullptr, this, 0, m_hWnd, nullptr );

}




void CAXWindow::SetStatusWindow( HWND hWndStatus )
{
    m_hWndStatus = hWndStatus;
}

HRESULT CAXWindow::SetStatusText( LPCOLESTR pszStatusText )
{
    if ( nullptr == pszStatusText )
        return E_POINTER;

#ifndef _UNICODE
    char status[MAX_PATH];
    // Convert the Wide string to char
    WideCharToMultiByte( CP_ACP, 0, pszStatusText, -1, status, MAX_PATH, nullptr, nullptr );

    if ( IsWindow( m_hWndStatus ) )
        SendMessage( m_hWndStatus, SB_SETTEXT, ( WPARAM )0, ( LPARAM )status );

#else

    if ( IsWindow( m_hWndStatus ) )
        SendMessage( m_hWndStatus, SB_SETTEXT, ( WPARAM )0, ( LPARAM )pszStatusText );

#endif

    return ( S_OK );
}

void CAXWindow::SetParent( HWND hWndParent )
{
    m_hWnd = hWndParent;
}

HRESULT CAXWindow::SetMenu( HMENU hmenuShared, HOLEMENU holemenu, HWND hwndActiveObject )
{
    UNREFERENCED_PARAMETER( hmenuShared );
    UNREFERENCED_PARAMETER( holemenu );
    UNREFERENCED_PARAMETER( hwndActiveObject );
    return E_NOTIMPL;
}

//////////////////////////////////////////////////////////////////////////
// Called when the browser object is about to display its context menu.
STDMETHODIMP CAXWindow::ShowContextMenu( DWORD dwID, POINT * ppt, IUnknown * pcmdtReserved, IDispatch  * pdispReserved )
{


    // We will return S_OK to tell the browser not to display its default context menu,
    // or return S_FALSE to let the browser show its default context menu. For this
    // example, we wish to disable the browser's default context menu.
    return   S_FALSE;//(S_OK);
}

// Called at initialization of the browser object UI. We can set various features of the browser object here.
STDMETHODIMP CAXWindow::GetHostInfo( DOCHOSTUIINFO * pInfo )
{
    pInfo->cbSize = sizeof( DOCHOSTUIINFO );

    // Set some flags. We don't want any 3D border. You can do other things like hide
    // the scroll bar (DOCHOSTUIFLAG_SCROLL_NO), display picture display (DOCHOSTUIFLAG_NOPICS),
    // disable any script running when the page is loaded (DOCHOSTUIFLAG_DISABLE_SCRIPT_INACTIVE),
    // open a site in a new browser window when the user clicks on some link (DOCHOSTUIFLAG_OPENNEWWIN),
    // and lots of other things. See the MSDN docs on the DOCHOSTUIINFO struct passed to us.
    pInfo->dwFlags = DOCHOSTUIFLAG_NO3DBORDER;

    // Set what happens when the user double-clicks on the object. Here we use the default.
    pInfo->dwDoubleClick = DOCHOSTUIDBLCLK_DEFAULT;


// 	pInfo->dwFlags = DOCHOSTUIFLAG_NO3DBORDER;
// 	pInfo->dwDoubleClick = DOCHOSTUIDBLCLK_DEFAULT;
// 	pInfo->dwFlags|=DOCHOSTUIFLAG_SCROLL_NO;




    return( S_OK );
}

// Called when the browser object shows its UI. This allows us to replace its menus and toolbars by creating our
// own and displaying them here.
STDMETHODIMP CAXWindow::ShowUI( DWORD dwID, IOleInPlaceActiveObject * pActiveObject, IOleCommandTarget * pCommandTarget, IOleInPlaceFrame * pFrame, IOleInPlaceUIWindow * pDoc )
{
    // We've already got our own UI in place so just return S_OK to tell the browser
    // not to display its menus/toolbars. Otherwise we'd return S_FALSE to let it do
    // that.

    //return S_FALSE;
    return( S_OK );
}

// Called when browser object hides its UI. This allows us to hide any menus/toolbars we created in ShowUI.
STDMETHODIMP CAXWindow::HideUI()
{
    return( S_OK );
}

// Called when the browser object wants to notify us that the command state has changed. We should update any
// controls we have that are dependent upon our embedded object, such as "Back", "Forward", "Stop", or "Home"
// buttons.
STDMETHODIMP CAXWindow::UpdateUI()
{
    // We update our UI in our window message loop so we don't do anything here.
    return( S_OK );
}

// Called from the browser object's IOleInPlaceActiveObject object's OnDocWindowActivate() function.
// This informs off of when the object is getting/losing the focus.
STDMETHODIMP CAXWindow::OnDocWindowActivate( BOOL fActivate )
{
    return( S_OK );
}

// Called from the browser object's IOleInPlaceActiveObject object's OnFrameWindowActivate() function.
STDMETHODIMP CAXWindow::OnFrameWindowActivate( BOOL fActivate )
{
    return( S_OK );
}

// Called from the browser object's IOleInPlaceActiveObject object's ResizeBorder() function.
STDMETHODIMP CAXWindow::ResizeBorder( LPCRECT prcBorder, IOleInPlaceUIWindow * pUIWindow, BOOL fRameWindow )
{
    return( S_OK );
}

// Called by the browser object to find where the host wishes the browser to get its options in the registry.
// We can use this to prevent the browser from using its default settings in the registry, by telling it to use
// some other registry key we've setup with the options we want.
STDMETHODIMP CAXWindow::GetOptionKeyPath( LPOLESTR * pchKey, DWORD dw )
{
    // Let the browser use its default registry settings.
    return( S_FALSE );
}

// Called by the browser object when it is used as a drop target. We can supply our own IDropTarget object,
// IDropTarget functions, and IDropTarget VTable if we want to determine what happens when someone drags and
// drops some object on our embedded browser object.
STDMETHODIMP CAXWindow::GetDropTarget( IDropTarget * pDropTarget, IDropTarget  * *ppDropTarget )
{

    // But for our purposes, we don't need an IDropTarget object, so we'll tell whomever is calling
    // us that we don't have one.
    return( S_FALSE );
}


// Called by the browser object to give us an opportunity to modify the URL to be loaded.
STDMETHODIMP CAXWindow::TranslateUrl( DWORD dwTranslate, OLECHAR * pchURLIn, OLECHAR  * *ppchURLOut )
{
    // We don't need to modify the URL. Note: We need to set ppchURLOut to 0 if we don't
    // return an OLECHAR (buffer) containing a modified version of pchURLIn.
    *ppchURLOut = 0;
    return( S_FALSE );
}

// Called from the browser object's IOleInPlaceActiveObject object's EnableModeless() function. Also
// called when the browser displays a modal dialog box.
// STDMETHODIMP CAXWindow::EnableModeless( BOOL fEnable )
// {
// 	return( S_OK );
// }

STDMETHODIMP CAXWindow::GetExternal( IDispatch  * *ppDispatch )
{

    *ppDispatch = 0;
    return( S_FALSE );
}

// Called by the browser when it does cut/paste to the clipboard. This allows us to block certain clipboard
// formats or support additional clipboard formats.
STDMETHODIMP CAXWindow::FilterDataObject( IDataObject * pDO, IDataObject  * *ppDORet )
{

    *ppDORet = 0;
    return( S_FALSE );
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

QEventSink::QEventSink() : m_cRefs( 1 )
{
}


STDMETHODIMP_( ULONG ) QEventSink::AddRef()
{
    return ++m_cRefs;
}


STDMETHODIMP_( ULONG ) QEventSink::Release()
{
    return --m_cRefs;
}


STDMETHODIMP QEventSink::QueryInterface( REFIID riid, void ** ppvObject )
{
    if ( !ppvObject )
        return E_POINTER;

    if ( IsEqualIID( riid, IID_IDispatch ) )
        *ppvObject = ( IDispatch * )this;
    else if ( IsEqualIID( riid, IID_IUnknown ) )
        *ppvObject = this;
    else
    {
        *ppvObject = nullptr;
        return E_NOINTERFACE;
    }

    AddRef();
    return S_OK;
}


STDMETHODIMP QEventSink::GetIDsOfNames( REFIID riid, OLECHAR ** rgszNames, unsigned int cNames, LCID lcid, DISPID * rgdispid )
{
    UNREFERENCED_PARAMETER( ( IID )riid );			// IID cast required for the MinGW compiler
    UNREFERENCED_PARAMETER( rgszNames );
    UNREFERENCED_PARAMETER( cNames );
    UNREFERENCED_PARAMETER( lcid );
    *rgdispid = DISPID_UNKNOWN;
    return DISP_E_UNKNOWNNAME;
}


STDMETHODIMP QEventSink::GetTypeInfo( unsigned int itinfo, LCID lcid, ITypeInfo ** pptinfo )
{
    UNREFERENCED_PARAMETER( itinfo );
    UNREFERENCED_PARAMETER( lcid );
    UNREFERENCED_PARAMETER( pptinfo );
    return E_NOTIMPL;
}

STDMETHODIMP QEventSink::GetTypeInfoCount( unsigned int * pctinfo )
{
    UNREFERENCED_PARAMETER( pctinfo );
    return E_NOTIMPL;
}



// class CDocumentSink :
// 	public IDispEventImpl<1, CDocumentSink, &DIID_HTMLDocumentEvents2, &LIBID_MSHTML, 4, 0>
// {
// public:
// 	BEGIN_SINK_MAP(CDocumentSink)
// 		SINK_ENTRY_EX(1, DIID_HTMLDocumentEvents2, DISPID_READYSTATECHANGE, OnReadyStateChange)
// 	END_SINK_MAP()
//
// 	STDMETHOD_(void, OnReadyStateChange)(IHTMLEventObj* ev);
//
//

//  case  DISPID_HTMLDOCUMENTEVENTS_ONHELP:
//  case  DISPID_HTMLDOCUMENTEVENTS_ONCLICK:
//  case  DISPID_HTMLDOCUMENTEVENTS_ONDBLCLICK:
//  case  DISPID_HTMLDOCUMENTEVENTS_ONKEYDOWN:
//  case  DISPID_HTMLDOCUMENTEVENTS_ONKEYUP:
//  case  DISPID_HTMLDOCUMENTEVENTS_ONKEYPRESS:
//  case  DISPID_HTMLDOCUMENTEVENTS_ONMOUSEDOWN :
//  case  DISPID_HTMLDOCUMENTEVENTS_ONMOUSEMOVE:
//  case  DISPID_HTMLDOCUMENTEVENTS_ONMOUSEUP:
//  case  DISPID_HTMLDOCUMENTEVENTS_ONMOUSEOUT:
//  case  DISPID_HTMLDOCUMENTEVENTS_ONMOUSEOVER:
//  case  DISPID_HTMLDOCUMENTEVENTS_ONREADYSTATECHANGE:
//  case  DISPID_HTMLDOCUMENTEVENTS_ONBEFOREUPDATE:
//  case  DISPID_HTMLDOCUMENTEVENTS_ONAFTERUPDATE:
//  case  DISPID_HTMLDOCUMENTEVENTS_ONROWEXIT:
//  case  DISPID_HTMLDOCUMENTEVENTS_ONROWENTER:
//  case  DISPID_HTMLDOCUMENTEVENTS_ONDRAGSTART:
//  case  DISPID_HTMLDOCUMENTEVENTS_ONSELECTSTART:
//  case  DISPID_HTMLDOCUMENTEVENTS_ONERRORUPDATE:
// 	 {
// 		 ::MessageBox( 0, L"click", 0, 0 );
//
//
//
// 	 }

// };

#include <mshtmdid.h>
#include <exdisp.h>

// Declare these as members of your IWebBrowser2 sink.


// template<class T>
// STDMETHODIMP QEventSink<T>::OnDocumentComplete( IDispatch * wbDisp, VARIANT * url )
// {
//     HRESULT hr;
//     QComPointer<IDispatch> pDocDisp;
//     QComPointer<IHTMLDocument2> pDoc;
//
//
//     IUnknown * wbDispUnk = nullptr;
//
//     // Sink only the topmost document. Slightly more complex logic will be needed
//     // if you wish to sink multiple pages embedded in a frameset.
//     hr = wbDisp->QueryInterface( IID_IUnknown, reinterpret_cast<void **>( &wbDispUnk ) );
//
//     if ( FAILED( hr ) )
//     {
//         goto cleanup;
//     }
//
//     //if ( wbDispUnk == browserUnk )
//     {
//         hr = QComPointer<CDocumentSink>::CreateInstance( &pSink );
//
//         if ( FAILED( hr ) )
//         {
//             goto cleanup;
//         }
//
//         // Get the current document from the WebBrowser.
//         // If you'll be surfing to sites with frames, and want to avoid sinking all but
//         // the top-level document - i.e., the frameset - make sure to sink only when the
//         // IUnknown obtained from wbDisp and the original IUnknown of the hosted
//         // WebBrowser control are equal.
//         hr = webOC->get_Document( &pDocDisp );
//
//         if ( FAILED( hr ) )
//         {
//             goto cleanup;
//         }
//
//         hr = pDocDisp->QueryInterface( &pSrcUnk );
//
//         if ( FAILED( hr ) )
//         {
//             goto cleanup;
//         }
//
//         // If this is not an HTML document (e.g., it's a Word doc or a PDF), don't sink.
//         pDoc = pDocDisp;
//
//         if ( !pDoc )
//         {
//             goto cleanup;
//         }
//
//         hr = Advise( pSrcUnk, pSink, DIID_HTMLDocumentEvents, &dwDocCookie );
//
//         if ( FAILED( hr ) )
//         {
//             goto cleanup;
//         }
//     }
//
// cleanup:
//     // Only smart pointers used - nothing to do here.
//     return hr;
// }

// void QEventSink::OnDocumentComplete()
// {
// 	static bool bo = false;
//
// 	if ( bo )
// 		return;
//
// 	//bo = true;
// 	IWebBrowser2	*	webBrowser  = m_pSink;
// 	IHTMLDocument 	*	doc			= nullptr;
// 	IHTMLDocument2 *	doc2		= nullptr;
// 	IHTMLWindow2 	*	win2		= nullptr;
//
// 	IDispatch * idisp = 0;
// 	webBrowser->get_Document( &idisp );
//
// 	if ( idisp && !doc )
// 		idisp->QueryInterface( IID_IHTMLDocument, ( void ** )&doc );
//
// 	if ( idisp && !doc2 )
// 		idisp->QueryInterface( IID_IHTMLDocument2, ( void ** )&doc2 );
//
// 	if ( doc2 && !win2 )
// 		doc2->get_parentWindow( &win2 );
//
// 	//doc2->put_onclick();
// 	//doc2->put_onkeydown();
// 	//
// 	// 	variant_t clickDispatch;
// 	// 	clickDispatch.vt = VT_DISPATCH;
// 	// 	clickDispatch.pdispVal = static_cast<IDispatch *>( this );
//
//
// 	//HRESULT hr = doc2->put_onkeydown(clickDispatch);
//
//
// 	IConnectionPointContainer * cpc = 0;
//
// 	if ( doc )
// 		doc->QueryInterface( IID_IConnectionPointContainer, ( void ** ) &cpc );
//
// 	IConnectionPoint * cp = 0;
//
// 	if ( cpc )
// 		cpc->FindConnectionPoint( DIID_HTMLDocumentEvents2, &cp );
//
// 	DWORD cookie;
//
// 	HRESULT hr;
//
// 	if ( cp )
// 		hr = cp->Advise( static_cast<IDispatch *>( this ), &cookie );
//
// 	if ( cp )
// 		cp->Release();
//
// 	if ( cpc )
// 		cpc->Release();
//
// 	if ( idisp )
// 		idisp->Release();
//
// 	if ( !doc || !doc2 || !win2 || hr != S_OK )
// 	{
// 		//release();
// 		return ;
// 	}
//
// 	return ;


// 	IWebBrowser2       *       webBrowser = m_pSink;
//    	IConnectionPointContainer * connectionPointContainer;
//     unsigned long              cookie;
//     IDispatch         *        document;
//
//
//     webBrowser->get_Document( &document );
//
//     if ( ! ( document->QueryInterface( IID_IConnectionPointContainer, ( void ** ) &connectionPointContainer ) == S_OK ) )
//     {
//         ::MessageBox( 0, L"xxx", 0, 0 );
//     }
//
//
//     IConnectionPoint * cpHTMLDocument = nullptr;
//     // make sure we\'re getting browser events
//     HRESULT hr = connectionPointContainer->FindConnectionPoint( DIID_HTMLDocumentEvents2, &cpHTMLDocument );
//
//     if ( FAILED( hr ) )
//     {
//         ::MessageBox( 0, L"DIID_HTMLDocumentEvents failed", 0, 0 );
//
//     }
//
//     //::MessageBox(0, "goin", 0, 0);
//     hr = cpHTMLDocument->Advise( static_cast<IDispatch *>( this ), &cookie );
//
//     if ( FAILED( hr ) )
//     {
//         ::MessageBox( 0, L"Advise failed", 0, 0 );
//     }

//}





STDMETHODIMP QEventSink::Invoke( DISPID dispid, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS * pDispParams, VARIANT * pvarResult, EXCEPINFO * pexecinfo, unsigned int * puArgErr )
{
    UNREFERENCED_PARAMETER( ( IID )riid );			// IID cast required for the MinGW compiler
    UNREFERENCED_PARAMETER( lcid );
    UNREFERENCED_PARAMETER( wFlags );
    UNREFERENCED_PARAMETER( pvarResult );
    UNREFERENCED_PARAMETER( pexecinfo );
    UNREFERENCED_PARAMETER( puArgErr );

    ASSERT( wFlags == DISPATCH_METHOD );


    switch ( dispid )
    {
            // Just some of the possible events ...
        case DISPID_BEFORENAVIGATE2:
            //m_pSink->OnBeforeNavigate2(pDispParams);
            break;

        case DISPID_COMMANDSTATECHANGE:
            //m_pSink->OnCommandStateChange(pDispParams);
            break;

        case DISPID_DOCUMENTCOMPLETE:
            //m_pSink->OnDocumentComplete(pDispParams);
            break;

        case DISPID_DOWNLOADBEGIN:
            //m_pSink->OnDownloadBegin(pDispParams);
            break;

        case DISPID_DOWNLOADCOMPLETE:
            //m_pSink->OnDownloadComplete(pDispParams);
            break;

        case DISPID_NAVIGATECOMPLETE2:
            //m_pSink->OnNavigateComplete2(pDispParams);
            // Check the argument's type.

// 			if (pDispParams->rgvarg[0].vt == (VT_BYREF|VT_VARIANT))
// 			{
// 				CComVariant varURL(*pDispParams->rgvarg[0].pvarVal);
// 				varURL.ChangeType(VT_BSTR);
//
// 				// strEventInfo is an object of type strstream.
// 				//
// 				strEventInfo << "NavigateComplete2: " << OLE2T(vtURL.bstrVal)	<< ends;
//
// 				::MessageBox(NULL, strEventInfo.str(), "Invoke", MB_OK);
// 			}
// 			break;
            break;

        case DISPID_NEWWINDOW3:
            {

                //m_pSink->OnNewWindow2(pDispParams);
                int x = 0;//merge on new window

                QBSTR bstr = pDispParams->rgvarg;
                *( pDispParams->rgvarg[0].pboolVal ) = VARIANT_TRUE;

                return S_OK;

            }
            break;

        case DISPID_NEWWINDOW2:
            {
                //merge perfect
                *( pDispParams->rgvarg[0].pboolVal ) = VARIANT_TRUE;

//                 if ( pDispParams->rgvarg[1].ppdispVal != NULL )
//                 {
//                     m_pWebBrowser->AddRef();
//                     *( pDispParams->rgvarg[1].ppdispVal ) = ( IDispatch * )	m_pWebBrowser;
//                 }

                break;


            }
            break;

        case DISPID_PROGRESSCHANGE:
            //m_pSink->OnProgressChange(pDispParams);
            break;

        case DISPID_PROPERTYCHANGE:
            //m_pSink->OnPropertyChange(pDispParams);
            break;

        case DISPID_STATUSTEXTCHANGE:
            //m_pSink->OnStatusTextChange(pDispParams);
            break;

        case DISPID_TITLECHANGE:
            //m_pSink->OnTitleChange(pDispParams);
            break;
    }

    return S_OK;
}




//////////////////////////////////////////////////////////////////////////
QWebBrowser::QWebBrowser( const QString & url )
{
    m_url = url;
}

inline QWebBrowser::~QWebBrowser()
{

}


bool QWebBrowser::Create( QWindow * pParent /* = nullptr */, int id, UINT style )
{
    QPanel::Create( pParent, id, style );
    GetAXWindow().CreateControl(  CLSID_WebBrowser );
    GetAXWindow().SetParent( GetHandle() );
    GetAXWindow().SetVisible( TRUE );
    GetAXWindow().SetFocus( TRUE );


    INTERNETFEATURELIST featureToEnable = FEATURE_TABBED_BROWSING;
    HRESULT hr =  CoInternetSetFeatureEnabled( featureToEnable, SET_FEATURE_ON_PROCESS, TRUE );

    //just check
    hr = CoInternetIsFeatureEnabled( featureToEnable, SET_FEATURE_ON_PROCESS );

//     if ( !m_url.IsEmpty() )
//         Navigate( m_url );


    m_eventCookie = ConnectEvents( DIID_DWebBrowserEvents2, static_cast<IUnknown *>( &m_EventSink ) );


    return true;
}


bool QWebBrowser::OnPreCreate( CREATESTRUCT & cs )
{
    QPanel::OnPreCreate( cs );
    cs.style = WS_VISIBLE | WS_CHILD ;
    cs.lpCreateParams = ( QPanel * )this; /*pt a atasa clasa ferestrei}; */
    return true;
}


bool QWebBrowser::OnDestroy()
{
    GetAXWindow().Remove();
    return true;
}


bool QWebBrowser::OnSize( int type, int cx, int cy )
{
    // position the container
    //SetLocation(0, 0, cx, cy);
    //
    GetAXWindow().SetLocation( 0, 0, cx, cy );


    return true;
}





void QWebBrowser::Navigate( LPCTSTR pTChar )
{
    GetAXWindow().Navigate( pTChar );

}


// Navigation operations

void QWebBrowser::GoBack()
{

    GetAXWindow().GoBack();

}

void QWebBrowser::GoForward()
{

    GetAXWindow().GoForward();

}

void QWebBrowser::GoHome()
{
    GetAXWindow().GoHome();

}
void QWebBrowser::GoSearch()
{
    GetAXWindow().GoSearch();

}


void QWebBrowser::Refresh()
{

    GetAXWindow().Refresh();

}

void QWebBrowser::Stop()
{
    GetAXWindow().Stop();

}



void QWebBrowser::Write( LPCTSTR string )
{
    GetAXWindow().Write( string );
}

void QWebBrowser::Clear()
{
    GetAXWindow().Clear();
}

bool QWebBrowser::Print()
{
    IWebBrowser2 * pweb = GetAXWindow().GetBrowser();

    if ( !pweb )
        return false;


    if ( pweb )
    {
        pweb->ExecWB( OLECMDID_PRINT, OLECMDEXECOPT_PROMPTUSER, NULL, NULL );
    }

    pweb->Release();
    return true;
}

//use
//ConnectEvents( IID_IPropertyNotifySink, &m_PropertyNotifySink );

//IID_IPropertyNotifySink
// BEGIN_INTERFACE_PART(PropertyNotifySink, IPropertyNotifySink)
// 	INIT_INTERFACE_PART(COleControlSite, PropertyNotifySink)
// 	STDMETHOD(OnChanged)(DISPID dispid);
// 	STDMETHOD(OnRequestEdit)(DISPID dispid);
// END_INTERFACE_PART(PropertyNotifySink)

DWORD  QWebBrowser::ConnectEvents( REFIID iid, LPUNKNOWN punkSink )
{

    // LPOLEOBJECT m_pObject;
    IUnknown * pUnk = GetAXWindow().GetUnknown();

    if ( !pUnk )
        return 0;

    IConnectionPointContainer * pcpc = nullptr;
    IConnectionPoint * pcp = nullptr;

    HRESULT hr = pUnk->QueryInterface( IID_IConnectionPointContainer, ( void ** )&pcpc );

    if ( SUCCEEDED( hr ) )
    {
        //IID_DWebBrowserEvents2;
        //IID_DWebBrowserEvents2;
        //DIID_DWebBrowserEvents2
        pcpc->FindConnectionPoint( iid, &pcp );
        pcpc->Release();
    }

    DWORD cookie = 0;
    pcp->Advise( punkSink, &cookie );

    pcp->Release();
    pUnk->Release();

    return cookie;
}
void QWebBrowser::DisconnectSink( REFIID iid, DWORD dwCookie )
{
    IUnknown * pUnk = GetAXWindow().GetUnknown();

    if ( dwCookie == 0 || pUnk == nullptr )
        return;

    LPCONNECTIONPOINTCONTAINER pConnPtCont;

    if ( SUCCEEDED( pUnk->QueryInterface( IID_IConnectionPointContainer, ( LPVOID * )&pConnPtCont ) ) )
    {
        ASSERT( pConnPtCont != NULL );
        LPCONNECTIONPOINT pConnPt = NULL;

        if ( SUCCEEDED( pConnPtCont->FindConnectionPoint( iid, &pConnPt ) ) )
        {
            ASSERT( pConnPt != NULL );
            pConnPt->Unadvise( dwCookie );
            pConnPt->Release();
        }

        pConnPtCont->Release();
    }

    pUnk->Release();
}



//////////////////////////////////////////////////////////////////////////

CHTMLWriter::CHTMLWriter( IUnknown * pUnk )
{
    m_bReleaseIWebBrowserPtr = true;
    m_pUnk = pUnk;
    m_pDoc = NULL;

    if ( m_pUnk )
    {
        if ( FAILED( m_pUnk->QueryInterface( IID_IWebBrowser2, ( void ** ) &m_pWB ) ) )
            m_pWB = NULL;
    }
    else
        m_pWB = NULL;
}

CHTMLWriter::CHTMLWriter( IWebBrowser2 * pWB )
{
    m_bReleaseIWebBrowserPtr = false;
    m_pUnk = NULL;
    m_pDoc = NULL;
    m_pWB = pWB;
}

CHTMLWriter::~CHTMLWriter( void )
{
    if ( m_pDoc )
        m_pDoc->Release();

    if ( m_bReleaseIWebBrowserPtr && m_pWB )
        m_pWB->Release();
}

bool CHTMLWriter::Write( LPCTSTR pszHTMLContent )
{
    if ( !pszHTMLContent )
        return false;

    if ( !GetDocumentPtr() )
        return false;

    IStream * pStream = NULL;
    IPersistStreamInit * pPSI = NULL;
    HGLOBAL hHTMLContent;
    HRESULT hr;
    bool bResult = false;

    // allocate global memory to copy the HTML content to
    hHTMLContent = ::GlobalAlloc( GPTR, ( ::_tcslen( pszHTMLContent ) + 1 ) * sizeof( TCHAR ) );

    if ( !hHTMLContent )
        return false;

    ::_tcscpy( ( TCHAR * ) hHTMLContent, pszHTMLContent );

    // create a stream object based on the HTML content
    hr = ::CreateStreamOnHGlobal( hHTMLContent, TRUE, &pStream );

    if ( SUCCEEDED( hr ) )
    {
        // request the IPersistStreamInit interface
        hr = m_pDoc->QueryInterface( IID_IPersistStreamInit, ( void ** ) &pPSI );

        if ( SUCCEEDED( hr ) )
        {
            // initialize the persist stream object
            hr = pPSI->InitNew();

            if ( SUCCEEDED( hr ) )
            {
                // load the data into it
                hr = pPSI->Load( pStream );

                if ( SUCCEEDED( hr ) )
                    bResult = true;
            }

            pPSI->Release();
        }

        // implicitly calls ::GlobalFree to free the global memory
        pStream->Release();
    }

    return bResult;
}

bool CHTMLWriter::GetDocumentPtr( void )
{
    if ( !m_pUnk && !m_pWB )
        return false;

    if ( m_pDoc )
    {
        m_pDoc->Release();
        m_pDoc = NULL;
    }

    IDispatch * pDisp = NULL;
    HRESULT hr;

    // get the document's IDispatch*
    hr = m_pWB->get_Document( &pDisp );

    if ( SUCCEEDED( hr ) )
    {
        m_pDoc = pDisp;
        return true;
    }
    else
        return false;
}

bool CHTMLWriter::Add( LPCTSTR pszHTMLContent )
{
    if ( !pszHTMLContent )
        return false;

    if ( !GetDocumentPtr() )
        return false;

    IHTMLDocument2 * pHTMLDoc = NULL;
    IHTMLElement * pElem = NULL;
    HRESULT hr;
    bool bResult = false;

    // get an interface to the document object
    hr = m_pDoc->QueryInterface( IID_IHTMLDocument2, ( void ** ) &pHTMLDoc );

    if ( SUCCEEDED( hr ) )
    {
        // get the body element of the document
        hr = pHTMLDoc->get_body( &pElem );

        if ( SUCCEEDED( hr ) )
        {
            // retrieve all the HTML content of the body object
            BSTR bstr;
            hr = pElem->get_innerHTML( &bstr );

            if ( SUCCEEDED( hr ) )
            {
                // append the desired content to the HTML content of the document
                _bstr_t bstrContent( bstr );
                bstrContent += pszHTMLContent;

                // set the new HTML content of the document
                hr = pElem->put_innerHTML( bstrContent );

                if ( SUCCEEDED( hr ) )
                    bResult = true;

                ::SysFreeString( bstr );
            }

            pElem->Release();
        }

        pHTMLDoc->Release();
    }

    return bResult;
}




// Print contents

// void SimpleBrowser::Print( LPCTSTR header, LPCTSTR footer )
// {
// 	if ( _Browser != NULL )
// 	{
//
// 		// construct two element SAFEARRAY;
// 		// first element is header string, second element is footer string
//
// 		HRESULT hr;
//
// 		VARIANT		header_variant;
// 		VariantInit( &header_variant );
// 		V_VT( &header_variant )   = VT_BSTR;
// 		V_BSTR( &header_variant ) = CString( header ).AllocSysString();
//
// 		VARIANT		footer_variant;
// 		VariantInit( &footer_variant );
// 		V_VT( &footer_variant )   = VT_BSTR;
// 		V_BSTR( &footer_variant ) = CString( footer ).AllocSysString();
//
// 		long index;
//
// 		SAFEARRAYBOUND	parameter_array_bound[1];
// 		SAFEARRAY	*	parameter_array = NULL;
//
// 		parameter_array_bound[0].cElements = 2;
// 		parameter_array_bound[0].lLbound   = 0;
//
// 		parameter_array = SafeArrayCreate( VT_VARIANT, 1, parameter_array_bound );
//
// 		index = 0;
// 		hr    = SafeArrayPutElement( parameter_array, &index, &header_variant );
//
// 		index = 1;
// 		hr    = SafeArrayPutElement( parameter_array, &index, &footer_variant );
//
// 		VARIANT	parameter;
// 		VariantInit( &parameter );
// 		V_VT( &parameter )    = VT_ARRAY | VT_BYREF;
// 		V_ARRAY( &parameter ) = parameter_array;
//
// 		// start printing browser contents
//
// 		hr = _Browser->ExecWB( OLECMDID_PRINT, OLECMDEXECOPT_DODEFAULT, &parameter, NULL );
//
// 		// Note: There is no simple way to determine that printing has completed.
// 		//       In fact, if the browser is destroyed while printing is in progress,
// 		//       only part of the contents will be printed.
//
// 		// release SAFEARRAY
//
// 		if ( !SUCCEEDED( hr ) )
// 		{
// 			VariantClear( &header_variant );
// 			VariantClear( &footer_variant );
//
// 			if ( parameter_array != NULL )
// 			{
// 				SafeArrayDestroy( parameter_array );
// 			}
// 		}
//
// 	}
// }

// HRESULT QWebBrowser::SetWebBrowserZoom( int nZoom )
// {
//     ASSERT( MIN_ZOOM <= nZoom && nZoom <= MAX_ZOOM );
//
//
//     QVariant varZoom( nZoom );
//     const HRESULT hr = m_pIWebBrowser2->ExecWB( OLECMDID_OPTICAL_ZOOM, OLECMDEXECOPT_DODEFAULT, &varZoom, NULL );
//
//     ASSERT( SUCCEEDED( hr ) );
//
//
//     //if ( SUCCEEDED( hr ) )
//     //UpdateZoomButtonValue();
//
//     return hr;
// }

/*
HRESULT CFeedBrowser::HtmlFindNext(const CString& strFind,BOOL bForward,BOOL bMatchCase,BOOL bWholeWordOnly)
{
	static BSTR bstrSpanWhole = L"Textedit";
	static BSTR bstrSpanChar  = L"Character";

	CComPtr<IDispatch> pHtmlDocDispatch = NULL;
	// Retrieve the document object.
	HRESULT hr = m_pBrowser->get_Document(&pHtmlDocDispatch);
	if(FAILED(hr))
		return hr;

	CComBSTR bstrFind = (LPCTSTR)strFind;
	CComBSTR bstrReplace = _T("<font style=\"background-color:yellow\">");
	bstrReplace += bstrFind;
	bstrReplace += _T("</font>");

	CComQIPtr<IHTMLDocument2>piDoc(pHtmlDocDispatch);
	CComPtr<IHTMLSelectionObject>piSel;
	CComPtr<IHTMLTxtRange>piRange;
	CComPtr<IDispatch>pdispRange;

	BSTR bstrBookMark=NULL;
	CComBSTR bstrFindLocal;
	VARIANT_BOOL b=VARIANT_FALSE;
	long lFlag=0;

	if (piDoc == NULL)
		return E_INVALIDARG;

	if (S_OK != piDoc->get_selection(&piSel))
		return S_FALSE;

	if (S_OK != (hr=piSel->createRange(&pdispRange)) || (pdispRange == NULL))
		return hr;

	if (S_OK != pdispRange->QueryInterface(&piRange))
		return S_FALSE;

	if (S_OK == piRange->get_text(&bstrFindLocal) && (bstrFindLocal))
	{
		piRange->select();
		piRange->collapse((VARIANT_BOOL)(bForward) ? false : true);

		if (bForward)
			piRange->moveEnd(bstrSpanWhole, 1, &lFlag);
		else
			piRange->moveStart(bstrSpanWhole, -1, &lFlag);

		piRange->getBookmark(&bstrBookMark);
	}

	if (bstrFind != NULL)
		bstrFindLocal = bstrFind;

	if (!bstrFindLocal)
		return S_FALSE;

	//////////////////
	if (!bForward)
	{
		CComBSTR bstrT;
		piRange->expand(bstrSpanWhole, &b);
		piRange->collapse((VARIANT_BOOL)false);
		piRange->moveStart(bstrSpanChar, -1, &lFlag);
		piRange->get_text(&bstrT);
		piRange->moveEnd(bstrSpanChar, 1, &lFlag);
		piRange->put_text(bstrT);
	}
	//////////////////

	piRange->expand(bstrSpanWhole, &b);
	lFlag=0;

	if (bstrBookMark)
		piRange->moveToBookmark(bstrBookMark, &b);
	if (bMatchCase)
		lFlag |= HTML_FLAG_FINDMATCHCASE;
	if (bWholeWordOnly)
		lFlag |= HTML_FLAG_FINDWHOLEWORD;

	CComBSTR rCmd = _T("Backcolor");
	while ((S_OK == piRange->findText(bstrFindLocal,((bForward) ? 0 : 0x80000000),lFlag, &b))
		&& (b))
	{
		//piRange->scrollIntoView((VARIANT_BOOL)(bForward) ? false : true);
		// piRange->select();
		CComVariant v = _T("yellow");
		piRange->execCommand(rCmd,VARIANT_FALSE,v,NULL);
		piRange->setEndPoint(CComBSTR(_T("StartToEnd")),piRange);
	}

	return S_OK;
}




# include <exdispid.h>
# include <Mshtml.h>
# include <Mshtmdid.h>
# include <shobjidl.h>

In the BEGIN_EVENTSINK_MAP (CHtmlViewTestView, its Automatically seeks the threshol A direct UI likes MSN s)
	ON_EVENT (CHtmlViewTestView, AFX_IDW_PANE_FIRST, DISPID_NEWWINDOW3, NewWindow3 VTS_PDISPATCH VTS_PBOOL VTS_I4 VTS_BSTR VTS_BSTR)
	END_EVENTSINK_MAP ()

void CHtmlViewTestView :: NewWindow3 (
		IDispatch ** ppDisp,
		VARIANT_BOOL * Cancel
		DWORD dwFlags, the
		BSTR bstrUrlContext,
		BSTR bstrUrl
		)
	{
		CDocTemplate * pDocTemplate = GetDocument () -> GetDocTemplate ();
		CDocument * pDocument = pDocTemplate-> OpenDocumentFile, with (NULL);
		POSITION pos = pDocument-> GetFirstViewPosition ();
		CHtmlViewTestView * pNewView = (CHtmlViewTestView *) pDocument-> GetNextView (pos);
		pNewView-> SetRegisterAsBrowser-(TRUE);
		* ppDisp = pNewView-> - GetApplication ();
	}


*/


